package com.ruoyi.web.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.ruoyi.web.dto.ComplainImportDTO;
import com.ruoyi.web.entity.BlackBaseInfo;
import com.ruoyi.web.entity.BlackComplainDetail;
import com.ruoyi.web.entity.BlackFileInfo;
import com.ruoyi.web.entity.BlackOperation;
import com.ruoyi.web.entity.enums.ComplainSourceEnum;
import com.ruoyi.web.entity.enums.GuangdongCityEnum;
import com.ruoyi.web.mapper.BlackBaseInfoMapper;
import com.ruoyi.web.mapper.BlackComplainDetailMapper;
import com.ruoyi.web.mapper.BlackFileInfoMapper;
import com.ruoyi.web.mapper.BlackOperationMapper;
import com.ruoyi.web.service.BlackCaseService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BlackCaseServiceImpl implements BlackCaseService {
    
    private static final Logger log = LoggerFactory.getLogger(BlackCaseServiceImpl.class);
    
    @Resource
    private BlackBaseInfoMapper baseInfoMapper;
    
    @Resource
    private BlackOperationMapper operationMapper;
    
    @Resource
    private BlackComplainDetailMapper complainDetailMapper;
    
    @Resource
    private BlackFileInfoMapper fileInfoMapper;
    
    @Resource
    private BlackBaseInfoMapper blackBaseInfoMapper;
    
    @Override
    public Map<String, Object> listBlackCase(Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            log.info("查询黑产案件列表，参数：{}", params);
            
            // 处理分页参数
            int pageNum = params.get("pageNum") == null ? 1 : Integer.parseInt(params.get("pageNum").toString());
            int pageSize = params.get("pageSize") == null ? 10 : Integer.parseInt(params.get("pageSize").toString());
            params.put("offset", (pageNum - 1) * pageSize);
            params.put("pageSize", pageSize);
            
            // 处理搜索参数，添加模糊查询
            processSearchParams(params);
            
            // 查询总数
            int total = baseInfoMapper.selectCount(params);
            
            // 查询列表
            List<BlackBaseInfo> list = baseInfoMapper.selectList(params);

            
            log.info("查询结果，总数：{}，列表：{}", total, list);
            
            result.put("total", total);
            result.put("rows", list);
            result.put("code", 200);
            result.put("msg", "查询成功");
        } catch (Exception e) {
            log.error("查询黑产案件列表失败", e);
            result.put("total", 0);
            result.put("rows", new ArrayList<>());
            result.put("code", 500);
            result.put("msg", "查询失败：" + e.getMessage());
        }
        
        return result;
    }

    /**
     * 处理搜索参数，添加模糊查询
     */
    private void processSearchParams(Map<String, Object> params) {
        // 需要模糊查询的字段列表
        String[] fuzzyFields = {
            "companyName",        // 公司名称
            "companyType",        // 公司类型
            "companyLegalName",   // 法人姓名
            "companyLegalIdno",   // 法人证件号
            "companyCity",        // 公司所在城市
            "companyAddress",     // 公司地址
            "contactName",        // 联系人姓名
            "contactType",        // 联系人类型
            "contactIdno",        // 联系人证件号
            "contactNo",          // 联系电话
            "createUser",         // 创建人
            "createName",         // 创建人姓名
            "createBranch"        // 创建机构
        };
        
        // 处理每个需要模糊查询的字段
        for (String field : fuzzyFields) {
            Object value = params.get(field);
            if (value != null && !value.toString().trim().isEmpty()) {
                // 添加模糊查询的百分号
                params.put(field, "%" + value.toString().trim() + "%");
            }
        }
    }

    @Override
    public Map<String, Object> getBlackCase(String id) {
        Map<String, Object> result = new HashMap<>();
        Map<String, Object> data = new HashMap<>();
        
        try {
            log.info("查询案件详情，id={}", id);
            
            // 查询基本信息
            BlackBaseInfo baseInfo = baseInfoMapper.selectById(id);
            log.info("查询基本信息结果：{}", baseInfo);
            
            // 查询运作模式
            BlackOperation operation = operationMapper.selectByBaseId(id);
            log.info("查询运作模式结果：{}", operation);
            
            // 查询投诉详情
            List<BlackComplainDetail> complainDetails = complainDetailMapper.selectByBaseId(id);
            // 转换为前端需要的格式
            List<Map<String, Object>> formattedComplainDetails = new ArrayList<>();
            for (BlackComplainDetail detail : complainDetails) {
                Map<String, Object> map = new HashMap<>();
                map.put("id", detail.getId());
                map.put("baseId", detail.getBaseId());
                map.put("complainNo", detail.getComplainNo());
                map.put("complainName", detail.getComplainName());
                map.put("complainSource", detail.getComplainSource());
                map.put("complainContact", detail.getComplainContact());
                map.put("amount", detail.getAmount());
                map.put("damageAmount", detail.getDamageAmount());
                map.put("complainAddress", detail.getComplainAddress());
                map.put("complainStatus", detail.getComplainStatus());
                // 添加缺失的字段
                map.put("registrant", detail.getRegistrant());          // 登记人
                map.put("cityCode", detail.getCityCode());             // 所属地市编码
                map.put("cityName", detail.getCityName());             // 所属地市名称
                map.put("firstComplainTime", detail.getFirstComplainTime()); // 首次投诉时间
                map.put("complainSolution", detail.getComplainSolution()); // 投诉方案
                map.put("createTime", detail.getCreateTime());         // 创建时间
                map.put("updateTime", detail.getUpdateTime());         // 更新时间
                map.put("createBy", detail.getCreateBy());             // 创建人
                map.put("updateBy", detail.getUpdateBy());             // 更新人
                map.put("isDelete", detail.getIsDelete());             // 是否删除
                
                formattedComplainDetails.add(map);
            }
            log.info("查询投诉详情结果：{}", formattedComplainDetails);
            
            // 查询附件信息
            List<BlackFileInfo> fileInfos = fileInfoMapper.selectByBaseId(id);
            log.info("查询附件信息结果：{}", fileInfos);
            
            data.put("blackBaseInfo", baseInfo);
            data.put("blackOperation", operation);
            data.put("blackComplainDetails", formattedComplainDetails);
            data.put("blackFileInfos", fileInfos);
            
            result.put("msg", "操作成功");
            result.put("code", 200);
            result.put("data", data);
        } catch (Exception e) {
            log.error("查询案件详情失败", e);
            result.put("msg", "查询失败：" + e.getMessage());
            result.put("code", 500);
        }
        
        return result;
    }

    @Override
    @Transactional
    public Map<String, Object> addBlackCase(Map<String, Object> params) throws Exception {
        Map<String, Object> result = new HashMap<>();
        
        try {
            log.info("添加黑产案件，参数：{}", params);
            
            // 生成ID
            String id = UUID.randomUUID().toString().replace("-", "");
            
            // 处理基本信息
            Map<String, Object> baseInfoMap = (Map<String, Object>) params.get("blackBaseInfo");
            BlackBaseInfo baseInfo = new BlackBaseInfo();
            baseInfo.setId(id);
            baseInfo.setCompanyName((String) baseInfoMap.get("companyName"));
            baseInfo.setCompanyType((String) baseInfoMap.get("companyType"));
            baseInfo.setCompanyLegalName((String) baseInfoMap.get("companyLegalName"));
            baseInfo.setCompanyLegalIdno((String) baseInfoMap.get("companyLegalIdno"));
            baseInfo.setCompanyCity((String) baseInfoMap.get("companyCity"));
            baseInfo.setCompanyAddress((String) baseInfoMap.get("companyAddress"));
            baseInfo.setContactName((String) baseInfoMap.get("contactName"));
            baseInfo.setContactType((String) baseInfoMap.get("contactType"));
            baseInfo.setContactIdno((String) baseInfoMap.get("contactIdno"));
            baseInfo.setContactNo((String) baseInfoMap.get("contactNo"));
            baseInfo.setCreateUser((String) baseInfoMap.get("createUser"));
            baseInfo.setCreateName((String) baseInfoMap.get("createName"));
            baseInfo.setCreateBranch((String) baseInfoMap.get("createBranch"));
            baseInfo.setCreateTime(new Date());
            baseInfo.setModifyUser((String) baseInfoMap.get("createUser"));
            baseInfo.setModifyTime(new Date());
            
            baseInfoMapper.insert(baseInfo);
            
            // 处理运作模式
            Map<String, Object> operationMap = (Map<String, Object>) params.get("blackOperation");
            if (operationMap != null) {
                BlackOperation operation = new BlackOperation();
                operation.setId(UUID.randomUUID().toString().replace("-", ""));
                operation.setBaseId(id);
                operation.setGetCustChannel((String) operationMap.get("getCustChannel"));
                operation.setAccountName((String) operationMap.get("accountName"));
                // 处理日期字符串转换
                String registerDate = (String) operationMap.get("registerDate");
                if (registerDate != null && !registerDate.isEmpty()) {
                    try {
                        operation.setRegisterDate(new SimpleDateFormat("yyyy-MM-dd").parse(registerDate));
                    } catch (ParseException e) {
                        log.warn("解析注册日期失败：{}", registerDate, e);
                        operation.setRegisterDate(null);
                    }
                }
                operation.setComplainMaterial((String) operationMap.get("complainMaterial"));
                operation.setChainCust((String) operationMap.get("chainCust"));
                operation.setCustOrigin((String) operationMap.get("custOrigin"));
                operation.setAmountType((String) operationMap.get("amountType"));
                // 处理金额
                Object amountObj = operationMap.get("amount");
                if (amountObj != null) {
                    if (amountObj instanceof Number) {
                        operation.setAmount(new BigDecimal(amountObj.toString()));
                    } else if (amountObj instanceof String && !((String) amountObj).isEmpty()) {
                        operation.setAmount(new BigDecimal((String) amountObj));
                    }
                }
                
                operationMapper.insert(operation);
            }
            
            // 处理投诉详情
            List<Map<String, Object>> complainDetails = (List<Map<String, Object>>) params.get("blackComplainDetails");
            if (complainDetails != null && !complainDetails.isEmpty()) {
                for (Map<String, Object> detail : complainDetails) {
                    BlackComplainDetail complainDetail = new BlackComplainDetail();
                    complainDetail.setId(UUID.randomUUID().toString().replace("-", ""));
                    complainDetail.setBaseId(id);
                    complainDetail.setComplainName((String) detail.get("complainName"));
                    complainDetail.setComplainSource((String) detail.get("complainSource"));
                    complainDetail.setComplainContact((String) detail.get("complainContact"));
                    complainDetail.setComplainAddress((String) detail.get("complainAddress"));
                    complainDetail.setComplainStatus((String) detail.get("complainStatus"));
                    
                    // 处理金额
                    Object amountObj = detail.get("amount");
                    if (amountObj != null) {
                        if (amountObj instanceof Number) {
                            complainDetail.setAmount(new BigDecimal(amountObj.toString()));
                        } else if (amountObj instanceof String && !((String) amountObj).isEmpty()) {
                            complainDetail.setAmount(new BigDecimal((String) amountObj));
                        }
                    }
                    
                    // 处理损失金额
                    Object damageAmountObj = detail.get("damageAmount");
                    if (damageAmountObj != null) {
                        if (damageAmountObj instanceof Number) {
                            complainDetail.setDamageAmount(new BigDecimal(damageAmountObj.toString()));
                        } else if (damageAmountObj instanceof String && !((String) damageAmountObj).isEmpty()) {
                            complainDetail.setDamageAmount(new BigDecimal((String) damageAmountObj));
                        }
                    }
                    
                    validateComplainDetail(complainDetail);
                    
                    complainDetailMapper.insert(complainDetail);
                    log.info("保存投诉详情成功：{}", complainDetail);
                }
            }
            
            // 处理文件信息
            List<Map<String, Object>> fileInfos = (List<Map<String, Object>>) params.get("blackFileInfos");
            // 先删除该案件的所有文件信息
            fileInfoMapper.deleteByBaseId(id);
            log.info("清空案件文件信息，baseId={}", id);
            
            // 如果有新的文件信息，则保存
            if (fileInfos != null && !fileInfos.isEmpty()) {
                for (Map<String, Object> fileInfo : fileInfos) {
                    BlackFileInfo blackFileInfo = new BlackFileInfo();
                    blackFileInfo.setId(UUID.randomUUID().toString().replace("-", ""));
                    blackFileInfo.setBaseId(id);
                    blackFileInfo.setFileName((String) fileInfo.get("fileName"));
                    blackFileInfo.setFilePath((String) fileInfo.get("filePath"));
                    blackFileInfo.setUploadUser((String) fileInfo.get("uploadUser"));
                    
                    // 处理上传时间
                    Object uploadTimeObj = fileInfo.get("uploadTime");
                    if (uploadTimeObj instanceof String) {
                        try {
                            // 尝试多种日期格式
                            String uploadTimeStr = (String) uploadTimeObj;
                            Date uploadTime = null;
                            try {
                                // 尝试格式 "yyyy-MM-dd'T'HH:mm:ss.SSS"
                                uploadTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").parse(uploadTimeStr);
                            } catch (Exception e1) {
                                try {
                                    // 尝试格式 "yyyy-MM-dd HH:mm:ss"
                                    uploadTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(uploadTimeStr);
                                } catch (Exception e2) {
                                    // 如果都失败，使用当前时间
                                    uploadTime = new Date();
                                    log.warn("无法解析上传时间：{}，使用当前时间", uploadTimeStr);
                                }
                            }
                            blackFileInfo.setUploadTime(uploadTime);
                        } catch (Exception e) {
                            // 如果解析失败，使用当前时间
                            blackFileInfo.setUploadTime(new Date());
                            log.warn("解析上传时间失败，使用当前时间", e);
                        }
                    } else if (uploadTimeObj instanceof Date) {
                        blackFileInfo.setUploadTime((Date) uploadTimeObj);
                    } else {
                        // 如果没有时间或格式不对，使用当前时间
                        blackFileInfo.setUploadTime(new Date());
                    }
                    
                    // 保存文件信息
                    fileInfoMapper.insert(blackFileInfo);
                    log.info("保存文件信息成功：{}", blackFileInfo);
                }
            }
            
            result.put("code", 200);
            result.put("msg", "添加成功");
            result.put("data", id);  // 返回新增记录的ID
            
            log.info("添加黑产案件成功，id={}", id);
        } catch (Exception e) {
            log.error("添加黑产案件失败", e);
            result.put("code", 500);
            result.put("msg", "添加失败：" + e.getMessage());
            throw e; // 回滚事务
        }
        
        return result;
    }

    @Override
    @Transactional
    public Map<String, Object> updateBlackCase(Map<String, Object> params) throws Exception {
        Map<String, Object> result = new HashMap<>();
        
        try {
            log.info("更新黑产案件，参数：{}", params);
            
            // 处理基本信息
            Map<String, Object> baseInfoMap = (Map<String, Object>) params.get("blackBaseInfo");
            Object idObj = baseInfoMap.get("id");
            String baseId = idObj != null ? idObj.toString() : null;  // 安全地转换为字符串
            
            BlackBaseInfo baseInfo = new BlackBaseInfo();
            baseInfo.setId(baseId);
            baseInfo.setCompanyName((String) baseInfoMap.get("companyName"));
            baseInfo.setCompanyType((String) baseInfoMap.get("companyType"));
            baseInfo.setCompanyLegalName((String) baseInfoMap.get("companyLegalName"));
            baseInfo.setCompanyLegalIdno((String) baseInfoMap.get("companyLegalIdno"));
            baseInfo.setCompanyCity((String) baseInfoMap.get("companyCity"));
            baseInfo.setCompanyAddress((String) baseInfoMap.get("companyAddress"));
            baseInfo.setContactName((String) baseInfoMap.get("contactName"));
            baseInfo.setContactType((String) baseInfoMap.get("contactType"));
            baseInfo.setContactIdno((String) baseInfoMap.get("contactIdno"));
            baseInfo.setContactNo((String) baseInfoMap.get("contactNo"));
            baseInfo.setModifyUser((String) baseInfoMap.get("modifyUser"));
            baseInfo.setModifyTime(new Date());
            
            baseInfoMapper.updateById(baseInfo);
            
            // 处理运作模式
            Map<String, Object> operationMap = (Map<String, Object>) params.get("blackOperation");
            if (operationMap != null) {
                BlackOperation operation = new BlackOperation();
                operation.setBaseId(baseId);
                operation.setGetCustChannel((String) operationMap.get("getCustChannel"));
                operation.setAccountName((String) operationMap.get("accountName"));
                
                // 处理日期字符串转换
                String registerDate = (String) operationMap.get("registerDate");
                if (registerDate != null && !registerDate.isEmpty()) {
                    try {
                        operation.setRegisterDate(new SimpleDateFormat("yyyy-MM-dd").parse(registerDate));
                    } catch (ParseException e) {
                        log.warn("解析注册日期失败：{}", registerDate, e);
                        operation.setRegisterDate(null);
                    }
                }
                
                operation.setComplainMaterial((String) operationMap.get("complainMaterial"));
                operation.setChainCust((String) operationMap.get("chainCust"));
                operation.setCustOrigin((String) operationMap.get("custOrigin"));
                operation.setAmountType((String) operationMap.get("amountType"));
                // 处理金额
                Object amountObj = operationMap.get("amount");
                if (amountObj != null) {
                    if (amountObj instanceof Number) {
                        operation.setAmount(new BigDecimal(amountObj.toString()));
                    } else if (amountObj instanceof String && !((String) amountObj).isEmpty()) {
                        operation.setAmount(new BigDecimal((String) amountObj));
                    }
                }
                
                operationMapper.updateByBaseId(operation);
            }
            
            // 处理投诉详情
            List<Map<String, Object>> complainDetails = (List<Map<String, Object>>) params.get("blackComplainDetails");

            if (CollectionUtils.isNotEmpty(complainDetails)) {
            // 先删除原有的投诉详情
            complainDetailMapper.deleteByBaseId(baseId);
            
            // 保存新的投诉详情
                for (Map<String, Object> detailMap : complainDetails) {
                    BlackComplainDetail detail = createComplainDetail(detailMap, baseId);
                    validateComplainDetail(detail);  // 验证投诉详情
                    complainDetailMapper.insert(detail);
                    log.info("保存投诉详情成功：{}", detail);
                }
            }
            
            // 处理文件信息
            List<Map<String, Object>> fileInfos = (List<Map<String, Object>>) params.get("blackFileInfos");
            // 先删除该案件的所有文件信息
            fileInfoMapper.deleteByBaseId(baseId);
            log.info("清空案件文件信息，baseId={}", baseId);
            
            // 如果有新的文件信息，则保存
            if (fileInfos != null && !fileInfos.isEmpty()) {
                for (Map<String, Object> fileInfo : fileInfos) {
                    BlackFileInfo blackFileInfo = new BlackFileInfo();
                    blackFileInfo.setId(UUID.randomUUID().toString().replace("-", ""));
                    blackFileInfo.setBaseId(baseId);
                    blackFileInfo.setFileName((String) fileInfo.get("fileName"));
                    blackFileInfo.setFilePath((String) fileInfo.get("filePath"));
                    blackFileInfo.setUploadUser((String) fileInfo.get("uploadUser"));
                    
                    // 处理上传时间
                    Object uploadTimeObj = fileInfo.get("uploadTime");
                    if (uploadTimeObj instanceof String) {
                        try {
                            // 尝试多种日期格式
                            String uploadTimeStr = (String) uploadTimeObj;
                            Date uploadTime = null;
                            try {
                                // 尝试格式 "yyyy-MM-dd'T'HH:mm:ss.SSS"
                                uploadTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").parse(uploadTimeStr);
                            } catch (Exception e1) {
                                try {
                                    // 尝试格式 "yyyy-MM-dd HH:mm:ss"
                                    uploadTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(uploadTimeStr);
                                } catch (Exception e2) {
                                    // 如果都失败，使用当前时间
                                    uploadTime = new Date();
                                    log.warn("无法解析上传时间：{}，使用当前时间", uploadTimeStr);
                                }
                            }
                            blackFileInfo.setUploadTime(uploadTime);
                        } catch (Exception e) {
                            // 如果解析失败，使用当前时间
                            blackFileInfo.setUploadTime(new Date());
                            log.warn("解析上传时间失败，使用当前时间", e);
                        }
                    } else if (uploadTimeObj instanceof Date) {
                        blackFileInfo.setUploadTime((Date) uploadTimeObj);
                    } else {
                        // 如果没有时间或格式不对，使用当前时间
                        blackFileInfo.setUploadTime(new Date());
                    }
                    
                    // 保存文件信息
                    fileInfoMapper.insert(blackFileInfo);
                    log.info("保存文件信息成功：{}", blackFileInfo);
                }
            }
            
            result.put("code", 200);
            result.put("msg", "更新成功");
            
            log.info("更新黑产案件成功，id={}", baseId);
        } catch (Exception e) {
            log.error("更新黑产案件失败", e);
            result.put("code", 500);
            result.put("msg", "更新失败：" + e.getMessage());
            throw e; // 回滚事务
        }
        
        return result;
    }

    // 在保存投诉详情之前，确保所有字段都被正确设置
    private BlackComplainDetail createComplainDetail(Map<String, Object> detailMap, String baseId) {
        BlackComplainDetail detail = new BlackComplainDetail();
        if(StringUtils.isNotEmpty(MapUtils.getString(detailMap, "id"))){
            detail.setId(MapUtils.getString(detailMap, "id"));
        } else {
            detail.setId(UUID.randomUUID().toString().replace("-", ""));
        }
        
        // 设置基础信息
        detail.setBaseId(baseId);
        detail.setIsDelete("0");
        
        // 设置投诉信息
        detail.setComplainNo(MapUtils.getString(detailMap, "complainNo"));
        detail.setComplainName(MapUtils.getString(detailMap, "complainName"));
        detail.setComplainSource((String) detailMap.get("complainSource"));
        detail.setComplainContact((String) detailMap.get("complainContact"));
        detail.setComplainAddress((String) detailMap.get("complainAddress"));
        detail.setComplainStatus((String) detailMap.get("complainStatus"));
        detail.setComplainSolution(MapUtils.getString(detailMap, "complainSolution"));
        
        // 设置金额信息
        Object amountObj = MapUtils.getObject(detailMap, "amount");
        if (amountObj != null) {
            if (amountObj instanceof Number) {
                detail.setAmount(new BigDecimal(amountObj.toString()));
            } else if (amountObj instanceof String && StringUtils.isNotBlank((String) amountObj)) {
                detail.setAmount(new BigDecimal((String) amountObj));
            }
        }
        
        Object damageAmountObj = MapUtils.getObject(detailMap, "damageAmount");
        if (damageAmountObj != null) {
            if (damageAmountObj instanceof Number) {
                detail.setDamageAmount(new BigDecimal(damageAmountObj.toString()));
            } else if (damageAmountObj instanceof String && StringUtils.isNotBlank((String) damageAmountObj)) {
                detail.setDamageAmount(new BigDecimal((String) damageAmountObj));
            }
        }
        
        // 设置地区信息
        detail.setCityCode(MapUtils.getString(detailMap, "cityCode"));
        detail.setCityName(MapUtils.getString(detailMap, "cityName"));
        
        // 设置登记人
        detail.setRegistrant(MapUtils.getString(detailMap, "registrant"));
        
        // 设置投诉时间
        String firstComplainTime = MapUtils.getString(detailMap, "firstComplainTime");
        if (StringUtils.isNotBlank(firstComplainTime)) {
            try {
                // 尝试解析日期，支持多种格式
                String[] possiblePatterns = {
                    "yyyy-MM-dd",
                    "yyyy-MM-dd HH:mm:ss",
                    "yyyy/MM/dd",
                    "yyyy/MM/dd HH:mm:ss"
                };
                detail.setFirstComplainTime(DateUtils.parseDate(firstComplainTime, possiblePatterns));
            } catch (ParseException e) {
                log.warn("解析投诉时间失败：{}，使用当前时间", firstComplainTime, e);
                detail.setFirstComplainTime(new Date());
            }
        }
        
        // 设置创建和更新信息
        Date now = new Date();
        detail.setCreateTime(now);
        detail.setUpdateTime(now);
        detail.setCreateBy(getCurrentUserId());  // 需要实现获取当前用户ID的方法
        detail.setUpdateBy(getCurrentUserId());
        
        return detail;
    }

    // 验证投诉详情
    private void validateComplainDetail(BlackComplainDetail detail) {
        // 验证投诉来源
        String complainSource = detail.getComplainSource();
        if (StringUtils.isBlank(complainSource)) {
            throw new IllegalArgumentException("投诉来源不能为空");
        }
        
        // 验证投诉来源是否有效（假设有效值为 1,2,3,4,5）
        Set<String> validSources = new HashSet<>(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9"));
        if (!validSources.contains(complainSource)) {
            throw new IllegalArgumentException("无效的投诉来源: " + complainSource + 
                "，允许的值为：" + validSources);
        }
        
        // 其他验证...
    }

    // 添加获取当前用户ID的方法
    private String getCurrentUserId() {
        // TODO: 实现获取当前用户ID的逻辑
        return "system";  // 临时返回默认值
    }

    @Override
    public void exportToExcel(HttpServletResponse response, Map<String, Object> params) throws Exception {
        try {
            log.info("开始导出Excel，参数：{}", params);
            
            // 获取数据
            List<Map<String, Object>> baseInfoList = baseInfoMapper.selectBaseInfoWithOperation(params);
            log.info("查询到基本信息数据：{}条", baseInfoList.size());
            
            List<BlackComplainDetail> complainList = complainDetailMapper.selectList(params);
            log.info("查询到投诉详情数据：{}条", complainList.size());
            
            // 处理数据
            List<Map<String, Object>> baseInfoData = convertBaseInfoData(baseInfoList);
            List<Map<String, Object>> complainData = convertComplainData(complainList);
            
            // 设置响应头
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = "黑产案件信息.xlsx";
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);
            
            // 创建ExcelWriter（不使用模板，直接创建新的Excel）
            ExcelWriter writer = ExcelUtil.getWriter(true);
            writer.renameSheet("黑产机构基本信息");  // 重命名默认的sheet
            
            // 写入第一个sheet的数据
            // 写入表头
            writer.writeRow(Arrays.asList(
                "公司名称", "公司类型", "法人姓名", "法人证件号", "公司所在地", "公司地址",
                "获客渠道", "账号名称", "注册日期", "投诉材料", "约束客户", "客户信息来源",
                "收费方式", "涉及金额"
            ));
            // 写入数据
            for (Map<String, Object> row : baseInfoData) {
                writer.writeRow(Arrays.asList(
                    row.get("companyName"), row.get("companyType"), row.get("companyLegalName"),
                    row.get("companyLegalIdno"), row.get("companyCity"), row.get("companyAddress"),
                    row.get("getCustChannel"), row.get("accountName"), row.get("registerDate"),
                    row.get("complainMaterial"), row.get("chainCust"), row.get("custOrigin"),
                    row.get("amountType"), row.get("amount")
                ));
            }
            
            // 创建新的sheet
            writer.setSheet("黑产投诉详细信息");
            // 写入表头
            writer.writeRow(Arrays.asList(
                "机构名称", "投诉人姓名", "投诉来源", "联系方式", "投诉金额", "损失金额",
                "投诉地址", "投诉状态", "登记人", "所属地市", "首次投诉时间", "投诉方案",
                "创建时间", "更新时间"
            ));
            // 写入数据
            for (Map<String, Object> row : complainData) {
                writer.writeRow(Arrays.asList(
                    row.get("companyName"), row.get("complainName"), row.get("complainSource"),
                    row.get("complainContact"), row.get("amount"), row.get("damageAmount"),
                    row.get("complainAddress"), row.get("complainStatus"), row.get("registrant"),
                    row.get("cityName"), row.get("firstComplainTime"), row.get("complainSolution"),
                    row.get("createTime"), row.get("updateTime")
                ));
            }
            
            // 设置列宽
            writer.autoSizeColumnAll();
            
            // 写出到响应流
            writer.flush(response.getOutputStream());
            // 关闭writer
            writer.close();
                
            log.info("Excel导出完成");
        } catch (Exception e) {
            log.error("导出失败", e);
            throw new RuntimeException("导出失败：" + e.getMessage());
        }
    }

    // 转换基本信息数据
    private List<Map<String, Object>> convertBaseInfoData(List<Map<String, Object>> baseInfoList) {
        List<Map<String, Object>> data = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        
        log.info("开始转换基本信息数据，原始数据条数：{}", baseInfoList.size());
        
        for (Map<String, Object> info : baseInfoList) {
            Map<String, Object> rowData = new HashMap<>();
            
            // 添加数据转换日志
            log.debug("正在处理数据：{}", info);
            
            // 基本信息
            rowData.put("companyName", getStringValue(info.get("companyName")));
            rowData.put("companyType", getStringValue(info.get("companyType")));
            rowData.put("companyLegalName", getStringValue(info.get("companyLegalName")));
            rowData.put("companyLegalIdno", getStringValue(info.get("companyLegalIdno")));
            rowData.put("companyCity", getStringValue(info.get("companyCity")));
            rowData.put("companyAddress", getStringValue(info.get("companyAddress")));
            
            // 运营信息
            rowData.put("getCustChannel", getStringValue(info.get("getCustChannel")));
            rowData.put("accountName", getStringValue(info.get("accountName")));
            
            // 日期处理
            Object registerDateObj = info.get("registerDate");
            if (registerDateObj != null) {
                if (registerDateObj instanceof Date) {
                    rowData.put("registerDate", sdf.format(registerDateObj));
                } else {
                    rowData.put("registerDate", getStringValue(registerDateObj));
                }
            } else {
                rowData.put("registerDate", "");
            }
            
            rowData.put("complainMaterial", getStringValue(info.get("complainMaterial")));
            rowData.put("chainCust", getStringValue(info.get("chainCust")));
            rowData.put("custOrigin", getStringValue(info.get("custOrigin")));
            rowData.put("amountType", getStringValue(info.get("amountType")));
            rowData.put("amount", info.get("amount"));
            
            data.add(rowData);
            
            // 添加转换后的数据日志
            log.debug("转换后的数据：{}", rowData);
        }
        
        log.info("数据转换完成，转换后数据条数：{}", data.size());
        return data;
    }

    // 辅助方法：安全地获取字符串值
    private String getStringValue(Object obj) {
        return obj != null ? obj.toString() : "";
    }

    // 转换投诉详情数据
    private List<Map<String, Object>> convertComplainData(List<BlackComplainDetail> complainList) {
        List<Map<String, Object>> data = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        
        for (BlackComplainDetail detail : complainList) {
            Map<String, Object> rowData = new HashMap<>();
            // 获取机构名称
            String companyName = baseInfoMapper.getCompanyNameById(detail.getBaseId());
            rowData.put("companyName", companyName);
            rowData.put("complainName", detail.getComplainName());
            rowData.put("complainSource", getComplainSourceDesc(detail.getComplainSource()));
            rowData.put("complainContact", detail.getComplainContact());
            rowData.put("amount", detail.getAmount());
            rowData.put("damageAmount", detail.getDamageAmount());
            rowData.put("complainAddress", detail.getComplainAddress());
            rowData.put("complainStatus", detail.getComplainStatus());
            rowData.put("registrant", detail.getRegistrant());
            rowData.put("cityName", detail.getCityName());
            rowData.put("firstComplainTime", detail.getFirstComplainTime() != null ? 
                    sdf.format(detail.getFirstComplainTime()) : "");
            rowData.put("complainSolution", detail.getComplainSolution());
            rowData.put("createTime", detail.getCreateTime() != null ? 
                    sdf.format(detail.getCreateTime()) : "");
            rowData.put("updateTime", detail.getUpdateTime() != null ? 
                    sdf.format(detail.getUpdateTime()) : "");
            data.add(rowData);
        }
        return data;
    }

    // 获取投诉来源描述
    private String getComplainSourceDesc(String sourceCode) {
        if (StringUtils.isBlank(sourceCode)) {
            return "";
        }
        for (ComplainSourceEnum source : ComplainSourceEnum.values()) {
            if (source.getCode().equals(sourceCode)) {
                return source.getDesc();
            }
        }
        return sourceCode;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> importComplainDetails(MultipartFile file, String createBy) {
        List<String> errorMsgs = new ArrayList<>();
        try {
            EasyExcel.read(file.getInputStream(), ComplainImportDTO.class, new AnalysisEventListener<ComplainImportDTO>() {
                private List<BlackComplainDetail> dataList = new ArrayList<>();
                private int rowIndex = 1; // 从第一行开始计数

                @Override
                public void invoke(ComplainImportDTO data, AnalysisContext context) {
                    rowIndex++;
                    if (validateData(data, rowIndex)) {
                        BlackComplainDetail detail = convertToEntity(data, createBy);
                        dataList.add(detail);
                        if (dataList.size() >= 100) { // 每100条批量插入一次
                            complainDetailMapper.batchInsert(dataList);
                            dataList.clear();
                        }
                    }
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    if (!dataList.isEmpty()) {
                        complainDetailMapper.batchInsert(dataList);
                    }
                }

                private boolean validateData(ComplainImportDTO data, int rowIndex) {
                    if (data.getComplainName() == null || data.getComplainName().trim().isEmpty()) {
                        errorMsgs.add(String.format("第%d行：投诉人姓名不能为空", rowIndex));
                        return false;
                    }

                    // 验证城市名称
                    boolean validCity = false;
                    for (GuangdongCityEnum city : GuangdongCityEnum.values()) {
                        if (city.getName().equals(data.getCityName())) {
                            validCity = true;
                            break;
                        }
                    }
                    if (!validCity) {
                        errorMsgs.add(String.format("第%d行：无效的城市名称", rowIndex));
                        return false;
                    }

                    // 验证手机号格式
                    if (data.getComplainContact() != null && 
                        !data.getComplainContact().matches("^1[3-9]\\d{9}$")) {
                        errorMsgs.add(String.format("第%d行：联系方式格式不正确", rowIndex));
                        return false;
                    }

                    // 验证金额
                    if (data.getAmount() != null && data.getAmount().compareTo(BigDecimal.ZERO) < 0) {
                        errorMsgs.add(String.format("第%d行：诉求金额不能为负数", rowIndex));
                        return false;
                    }
                    if (data.getDamageAmount() != null && data.getDamageAmount().compareTo(BigDecimal.ZERO) < 0) {
                        errorMsgs.add(String.format("第%d行：损失金额不能为负数", rowIndex));
                        return false;
                    }

                    return true;
                }

                private BlackComplainDetail convertToEntity(ComplainImportDTO dto, String createBy) {
                    BlackComplainDetail entity = new BlackComplainDetail();
                    entity.setId(UUID.randomUUID().toString()); // 生成唯一ID
                    entity.setComplainName(dto.getComplainName());
                    entity.setComplainSource(dto.getComplainSource());
                    entity.setComplainContact(dto.getComplainContact());
                    entity.setAmount(dto.getAmount());
                    entity.setDamageAmount(dto.getDamageAmount());
                    entity.setComplainAddress(dto.getComplainAddress());
                    entity.setComplainSolution(dto.getComplainSolution());
                    entity.setFirstComplainTime(dto.getFirstComplainTime());
                    
                    // 设置城市信息
                    for (GuangdongCityEnum city : GuangdongCityEnum.values()) {
                        if (city.getName().equals(dto.getCityName())) {
                            entity.setCityCode(city.getCode());
                            entity.setCityName(city.getName());
                            break;
                        }
                    }
                    
                    // 设置基础字段
                    entity.setCreateBy(createBy);
                    entity.setUpdateBy(createBy);
                    entity.setCreateTime(new Date());
                    entity.setUpdateTime(new Date());
                    entity.setIsDelete("0");
                    
                    return entity;
                }
            }).sheet().doRead();
        } catch (Exception e) {
            log.error("导入失败", e);
            errorMsgs.add("导入失败：" + e.getMessage());
        }
        return errorMsgs;
    }

    @Override
    public List<ComplainImportDTO> getComplainDetailsForExport(Map<String, Object> params) {
        log.info("开始查询导出数据，参数：{}", params);
        
        // 移除分页参数，导出全部数据
        params.remove("pageNum");
        params.remove("pageSize");
        params.remove("offset");
        
        // 获取数据
        List<BlackComplainDetail> dataList = complainDetailMapper.selectListGroupByCN(params);
        log.info("查询到 {} 条数据", dataList.size());
        
        // 转换为DTO
        return dataList.stream().map(detail -> {
            ComplainImportDTO dto = new ComplainImportDTO();
            dto.setComplainName(detail.getComplainName());
            
            // 转换城市编码为城市名称
            String cityName = "";
            if (detail.getCityCode() != null) {
                for (GuangdongCityEnum city : GuangdongCityEnum.values()) {
                    if (city.getCode().equals(detail.getCityCode())) {
                        cityName = city.getName();
                        break;
                    }
                }
            }
            dto.setCityName(cityName);  // 设置城市名称
            
            // 转换投诉来源代码为描述
            String complainSourceDesc = "";
            if (detail.getComplainSource() != null) {
                for (ComplainSourceEnum source : ComplainSourceEnum.values()) {
                    if (source.getCode().equals(detail.getComplainSource())) {
                        complainSourceDesc = source.getDesc();
                        break;
                    }
                }
            }
            dto.setComplainSource(complainSourceDesc);  // 设置投诉来源描述
            
            dto.setFirstComplainTime(detail.getFirstComplainTime());
            dto.setComplainContact(detail.getComplainContact());
            dto.setComplainAddress(detail.getComplainAddress());
            dto.setAmount(detail.getAmount());
            dto.setDamageAmount(detail.getDamageAmount());
            dto.setComplainSolution(detail.getComplainSolution());
            return dto;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateComplainDetails(List<BlackComplainDetail> complainDetails) {
        complainDetailMapper.batchUpdate(complainDetails);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteComplainDetails(List<String> ids) {
        for (String id : ids) {
            complainDetailMapper.deleteByBaseId(id);
        }
    }

    @Override
    public Map<String, Object> listComplainDetails(Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 查询总数
            int total = complainDetailMapper.selectCount(params);
            
            // 查询列表
            List<BlackComplainDetail> list = complainDetailMapper.selectListGroupByCN(params);
            
            // 处理城市信息
            list.forEach(this::processCityInfo);

            //加入关联机构清单
            Map<String, List<String>> dataMap = new HashMap<>();
            list.forEach(detail -> {
                List<String> companyNameList = complainDetailMapper.selectByComplainNo(detail.getComplainNo());
                dataMap.put(detail.getId(),companyNameList);
            });
            String jsonData = convertMapToJson(dataMap);
            
            result.put("total", total);
            result.put("list", list);
            result.put("companyList",jsonData);
            result.put("code", 200);
            result.put("msg", "查询成功");
        } catch (Exception e) {
            log.error("查询投诉信息列表失败", e);
            result.put("total", 0);
            result.put("list", new ArrayList<>());
            result.put("code", 500);
            result.put("msg", "查询失败：" + e.getMessage());
        }
        
        return result;
    }

    private static String convertMapToJson(Map<String, List<String>> dataMap) {
        JSONObject jsonObject = new JSONObject();

        for (Map.Entry<String, List<String>> entry : dataMap.entrySet()) {
            // 将每个键值对添加到JSON对象中
            jsonObject.put(entry.getKey(), entry.getValue());
        }

        return jsonObject.toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateComplainDetail(BlackComplainDetail complainDetail) {
        // 参数校验
        if (complainDetail == null || StringUtils.isBlank(complainDetail.getId())) {
            throw new IllegalArgumentException("投诉信息ID不能为空");
        }
        
        // 验证数据
        validateComplainDetail(complainDetail);

        // 根据ID查询原记录
        BlackComplainDetail detail = complainDetailMapper.selectById(complainDetail.getId());
        if (detail == null) {
            throw new IllegalArgumentException("未找到对应的投诉记录");
        }
        
        log.info("原记录投诉编号: {}", detail.getComplainNo());
        log.info("更新内容: {}", complainDetail);
        
        // 更新数据
        int rows = complainDetailMapper.updateByassno(complainDetail, detail.getComplainNo());
        log.info("更新记录数: {}", rows);
        
        if (rows == 0) {
            throw new RuntimeException("更新失败，未找到符合条件的记录");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchAssociateComplain(List<String> baseIds, Map<String, Object> complainDetail, String createBy) {
        String currentUser = createBy;
        Date now = new Date();

        try {
            // 构建基础投诉信息
            BlackComplainDetail template = new BlackComplainDetail();
            template.setComplainNo((String) complainDetail.get("complainNo"));  // 设置投诉编号
            template.setComplainName((String) complainDetail.get("complainName"));
            template.setComplainSource((String) complainDetail.get("complainSource"));
            template.setComplainContact((String) complainDetail.get("complainContact"));
            template.setComplainAddress((String) complainDetail.get("complainAddress"));
            template.setAmount(new BigDecimal(String.valueOf(complainDetail.get("amount"))));
            template.setDamageAmount(new BigDecimal(String.valueOf(complainDetail.get("damageAmount"))));
            template.setComplainStatus((String) complainDetail.get("complainStatus"));
            template.setCityCode((String) complainDetail.get("cityCode"));
            template.setCityName((String) complainDetail.get("cityName"));
            
            // 处理日期转换
            String firstComplainTimeStr = (String) complainDetail.get("firstComplainTime");
            if (StringUtils.isNotBlank(firstComplainTimeStr)) {
                try {
                    // 尝试多种日期格式
                    Date firstComplainTime = DateUtils.parseDate(firstComplainTimeStr, 
                        "yyyy-MM-dd HH:mm:ss",
                        "yyyy-MM-dd",
                        "yyyy/MM/dd HH:mm:ss",
                        "yyyy/MM/dd"
                    );
                    template.setFirstComplainTime(firstComplainTime);
                } catch (ParseException e) {
                    log.error("日期转换失败", e);
                    throw new IllegalArgumentException("首次投诉时间格式不正确，支持的格式：yyyy-MM-dd HH:mm:ss, yyyy-MM-dd");
                }
            }
            
            template.setComplainSolution((String) complainDetail.get("complainSolution"));
            template.setCreateBy(currentUser);
            template.setUpdateBy(currentUser);
            template.setCreateTime(now);
            template.setUpdateTime(now);
            template.setIsDelete("0");

            // 批量生成投诉记录
            List<BlackComplainDetail> detailList = new ArrayList<>();
            for (String baseId : baseIds) {
                BlackComplainDetail detail = new BlackComplainDetail();
                BeanUtils.copyProperties(template, detail);
                // 生成32位的ID
                String id = UUID.randomUUID().toString().replace("-", "");
                detail.setId(id);
                detail.setBaseId(baseId);
                detailList.add(detail);
            }

            // 批量插入数据库
            complainDetailMapper.batchInsert(detailList);
        } catch (Exception e) {
            log.error("批量关联投诉信息失败", e);
            throw new RuntimeException("批量关联投诉信息失败：" + e.getMessage());
        }
    }

    @Override
    public void addComplaint(BlackComplainDetail detail) {
        if (detail.getCreateTime() == null) {
            detail.setCreateTime(new Date());
        }
        try {
            complainDetailMapper.insert(detail);
        }catch(Exception e){
            log.error("录入单条投诉记录失败", e);
            throw new RuntimeException("录入单条投诉记录失败：" + e.getMessage());
        }
    }

    /**
     * 处理城市信息
     */
    private void processCityInfo(BlackComplainDetail detail) {
        if (detail != null && detail.getCityCode() != null) {
            try {
                // 根据城市编码获取城市名称
                for (GuangdongCityEnum city : GuangdongCityEnum.values()) {
                    if (city.getCode().equals(detail.getCityCode())) {
                        detail.setCityName(city.getName());
                        break;
                    }
                }
            } catch (Exception e) {
                log.warn("处理城市信息失败，cityCode={}", detail.getCityCode(), e);
            }
        }
    }

    @Override
    public List<BlackBaseInfo> remoteSearchByCompanyName(String keyword, String companyType, 
                                                        String companyLegalName, String companyCity) {
        log.info("执行远程搜索公司名称，参数：keyword={}, companyType={}, companyLegalName={}, companyCity={}", 
                 keyword, companyType, companyLegalName, companyCity);
        
        Map<String, String> params = new HashMap<>();
        params.put("keyword", keyword);
        params.put("companyType", companyType);
        params.put("companyLegalName", companyLegalName);
        params.put("companyCity", companyCity);
        
        try {
            List<BlackBaseInfo> results = blackBaseInfoMapper.remoteSearchByCompanyName(params);
            log.info("远程搜索公司名称完成，找到 {} 条记录", results.size());
            return results;
        } catch (Exception e) {
            log.error("远程搜索公司名称失败", e);
            throw new RuntimeException("远程搜索公司名称失败：" + e.getMessage());
        }
    }

    @Override
    public List<BlackBaseInfo> remoteSearchByLegalName(String keyword, String companyName, 
                                                      String companyType, String companyCity) {
        log.info("执行远程搜索法人名称，参数：keyword={}, companyName={}, companyType={}, companyCity={}", 
                 keyword, companyName, companyType, companyCity);
        
        Map<String, String> params = new HashMap<>();
        params.put("keyword", keyword);
        params.put("companyName", companyName);
        params.put("companyType", companyType);
        params.put("companyCity", companyCity);
        
        try {
            List<BlackBaseInfo> results = blackBaseInfoMapper.remoteSearchByLegalName(params);
            log.info("远程搜索法人名称完成，找到 {} 条记录", results.size());
            return results;
        } catch (Exception e) {
            log.error("远程搜索法人名称失败", e);
            throw new RuntimeException("远程搜索法人名称失败：" + e.getMessage());
        }
    }

    @Override
    public List<BlackComplainDetail> remoteSearchByComplainName(String keyword, String cityCode, 
                                                               String complainSource, String complainStatus) {
        log.info("执行远程搜索投诉人名称，参数：keyword={}, cityCode={}, complainSource={}, complainStatus={}", 
                 keyword, cityCode, complainSource, complainStatus);
        
        Map<String, String> params = new HashMap<>();
        params.put("keyword", keyword);
        params.put("cityCode", cityCode);
        params.put("complainSource", complainSource);
        params.put("complainStatus", complainStatus);
        
        try {
            List<BlackComplainDetail> results = complainDetailMapper.remoteSearchByComplainName(params);
            log.info("远程搜索投诉人名称完成，找到 {} 条记录", results.size());
            return results;
        } catch (Exception e) {
            log.error("远程搜索投诉人名称失败", e);
            throw new RuntimeException("远程搜索投诉人名称失败：" + e.getMessage());
        }
    }
} 